package com.adms.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.adms.domain.Circular;
import com.adms.domain.CircularExample;
import com.adms.domain.CircularExample.Criteria;
import com.adms.domain.CircularMapper;
import com.adms.domain.CircularReply;
import com.adms.domain.CircularReplyMapper;
import com.adms.domain.Message;
import com.adms.domain.MessageMapper;
import com.adms.domain.User;
import com.adms.domain.UserMapper;
import com.adms.util.AdmsConfig;
import com.adms.util.AliMessageUtil;
import com.adms.util.FileUtil;
import com.adms.util.ShiroUtil;
import com.adms.websocket.WebSocketServer;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;

@Transactional
@Service
public class CircularService {

	@Autowired
	private CircularMapper circularMapper;
	@Autowired
	private CircularReplyMapper circularReplyMapper;
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private MessageMapper messageMapper;
	@Autowired
	private WebSocketServer webSocketServer;

	public Circular getByCircularId(Integer circularId) {
		return circularMapper.selectByPrimaryKey(circularId);
	}

	public Map<String, Object> getByCircularIdWithCanReply(Integer circularId) {
		return circularMapper.selectByCircularIdWithCanReply(circularId, ShiroUtil.getUser().getUserId());
	}

	public PageInfo<Circular> list(Circular circular, Boolean isSelf, String timeField, Date start, Date end,
			String key, String orderByClause, Integer pageNum, Integer pageSize, Integer navigatePages) {

		CircularExample ex = constructExample(circular, isSelf, timeField, start, end, orderByClause);

		PageHelper.startPage(pageNum, pageSize);
		List<Circular> circulars;
		if(StringUtil.isEmpty(key)) {
			circulars = circularMapper.selectByExample(ex);
		}else {
			circulars = circularMapper.selectByExampleAndKey(ex,"%" + key + "%");
		}
		return new PageInfo<>(circulars, navigatePages);
	}

	public PageInfo<Map<String, Object>> listWithCanReply(Circular circular, Boolean isSelf, String timeField,
			Date start, Date end, String key, String orderByClause, Integer pageNum, Integer pageSize,
			Integer navigatePages) {

		User loginUser = ShiroUtil.getUser();
		Integer loginUserId = loginUser.getUserId();
		String loginRole = loginUser.getRole();
		CircularExample ex = constructExample(circular, isSelf, timeField, start, end, orderByClause);

		PageHelper.startPage(pageNum, pageSize);
		List<Map<String, Object>> list;
		if(StringUtil.isEmpty(key)) {
			list = circularMapper.selectByExampleWithCanReply(ex, loginUserId, loginRole);
		}else {
			list = circularMapper.selectByExampleAndKeyWithCanReply(ex,"%" + key + "%",loginUserId, loginRole);
		}
		return new PageInfo<>(list, navigatePages);
	}

	public Map<Integer, Object> count(String timeField, Date start, Date end) {

		Map<Integer,Object> result = new HashMap<>();
		CircularExample ex = constructExample(null, null, timeField, start, end, null);
		
		List<Criteria> oredCriteria = ex.getOredCriteria();
		Criteria criteria = oredCriteria.get(0);
		criteria.andTypeEqualTo(1);
		long count1 = circularMapper.countByExample(ex);
		result.put(1, count1);
		criteria.getCriteria().remove(criteria.getCriteria().size()-1);
		criteria.andTypeEqualTo(2);
		long count2 = circularMapper.countByExample(ex);
		result.put(2, count2);
		criteria.getCriteria().remove(criteria.getCriteria().size()-1);
		criteria.andTypeEqualTo(3);
		long count3 = circularMapper.countByExample(ex);
		result.put(3, count3);
		
		return result;
	}

	private CircularExample constructExample(Circular circular, Boolean isSelf, String timeField, Date start, Date end,
			String orderByClause) {

		CircularExample ex = new CircularExample();
		Criteria or = ex.or();
		User loginUser = ShiroUtil.getUser();
		if (circular != null) {
			Integer type = circular.getType();
			Integer level = circular.getLevel();
			Integer fileType = circular.getFileType();
			Boolean messageNotice = circular.getMessageNotice();
			Integer signType = circular.getSignType();
			if (type != null) {
				or.andTypeEqualTo(type);
			}
			if (level != null) {
				or.andLevelEqualTo(level);
			}
			if (fileType != null) {
				or.andFileTypeEqualTo(fileType);
			}
			if (messageNotice != null) {
				or.andMessageNoticeEqualTo(messageNotice);
			}
			if(signType != null) {
				or.andSignTypeEqualTo(signType);
			}
		}

		if (isSelf != null && isSelf) {
			or.andUserIdEqualTo(loginUser.getUserId());
		}

		if (StringUtil.isNotEmpty(timeField)) {
			if (timeField.equals("createTime")) {
				if (start != null) {
					if (end != null) {
						or.andCreateTimeBetween(start, end);
					} else {
						or.andCreateTimeGreaterThanOrEqualTo(start);
					}
				} else {
					if (end != null) {
						or.andCreateTimeLessThanOrEqualTo(end);
					}
				}
			}
			if (timeField.equals("publishTime")) {
				if (start != null) {
					if (end != null) {
						or.andPublishTimeBetween(start, end);
					} else {
						or.andPublishTimeGreaterThanOrEqualTo(start);
					}
				} else {
					if (end != null) {
						or.andPublishTimeLessThanOrEqualTo(end);
					}
				}
			}
		}

		if (StringUtil.isNotEmpty(orderByClause)) {
			ex.setOrderByClause(orderByClause);
		} else {
			ex.setOrderByClause("circular.publish_time desc");
		}
		return ex;
	}

	public boolean publish(Circular circular, MultipartFile[] files) {
		User loginUser = ShiroUtil.getUser();
		circular.setUserId(loginUser.getUserId());
		circular.setUsername(loginUser.getUsername());
		// 上传pdf文件并将路径并将结果写入circular的pdfs字段
		if (files != null && files.length > 0) {
			circular.setFileType(1);
			String pdfs = "";
			for (MultipartFile file : files) {
				String filePath = FileUtil.uploadPdf(file);
				String url = FileUtil.getUrlByFilePath(filePath);
				pdfs += url + ",";
			}
			circular.setPdfs(pdfs.substring(0, pdfs.length() - 1));
		}
		circularMapper.insertSelective(circular);
		// 发送站内信和短信通知
		new Thread(new Runnable() {
			@Override
			public void run() {
				Integer type = circular.getType();
				List<User> relativeUsers = new ArrayList<>();
				String authUserIds = circular.getAuthUserIds();
				String authRoles = circular.getAuthRoles();
				if (type == 1) {
					relativeUsers = userMapper.selectByUserIds(authUserIds);
				}else if(type == 2) {
					relativeUsers = userMapper.selectByRoles(authRoles);
				}else if (type == 3) {
					relativeUsers = userMapper.selectByUserIds(authUserIds);
					relativeUsers.addAll(userMapper.selectByRoles(authRoles));
				}
				Integer circularId = circular.getCircularId();
				String title = circular.getTitle();
				String messageType = null;
				if (type == 1) {
					messageType = AdmsConfig.MESSAGE_TYPE_PUBLISHCIRCULAR_1;
				} else if (type == 2) {
					messageType = AdmsConfig.MESSAGE_TYPE_PUBLISHCIRCULAR_2;
				} else if (type == 3) {
					messageType = AdmsConfig.MESSAGE_TYPE_PUBLISHCIRCULAR_3;
				}
				Message message;
				Integer relativeUserId;
				for (User relativeUser : relativeUsers) {
					relativeUserId = relativeUser.getUserId();
					message = new Message();
					message.setUserId(relativeUserId);
					message.setCircularId(circularId);
					message.setTitle(title);
					message.setType(messageType);
					messageMapper.insertSelective(message);
					// 发送webSocket消息
					webSocketServer.sendMessage(relativeUserId, message);
					// 发送短信
					if (circular.getMessageNotice()) {
						AliMessageUtil.sendCircularNotice(relativeUser.getPhone());
					}
				}
			}
		}).start();
		return true;
	}

	public boolean respond(Integer circularId, String content, String signature) {
		User loginUser = ShiroUtil.getUser();
		CircularReply circularReply = new CircularReply();
		circularReply.setCircularId(circularId);
		circularReply.setUserId(loginUser.getUserId());
		circularReply.setUsername(loginUser.getUsername());
		circularReply.setSignature(signature);
		circularReply.setContent(content);
		circularReply.setAuditState(1);
		circularReplyMapper.insertSelective(circularReply);
		//判断是否发送站内信
		Circular circular = circularMapper.selectByPrimaryKey(circularId);
		if(circular.getType() == 1) {
			Integer relativeUserId = circular.getUserId();
			Message message = new Message();
			message.setUserId(relativeUserId);
			message.setCircularId(circularId);
			message.setCircularReplyId(circularReply.getReplyId());
			message.setTitle(circular.getTitle());
			message.setType(AdmsConfig.MESSAGE_TYPE_RESPONSECIRCLAR);
			messageMapper.insertSelective(message);
			// 发送webSocket消息
			webSocketServer.sendMessage(relativeUserId, message);
		}
		return true;
	}

	public boolean update(Circular circular) {
		circularMapper.updateByPrimaryKeySelective(circular);
		return true;
	}

	public boolean delete(int[] circularIds) {
		if (circularIds != null) {
			int length = circularIds.length;
			if (length > 0) {
				if (length == 1) {
					circularMapper.deleteByPrimaryKey(circularIds[0]);
				} else {
					circularMapper.deleteBatch(circularIds);
				}
			}
		}
		return true;
	}

}
